﻿using CodeGenerator.CSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Modifier = CodeGenerator.CSharp.Modifiers;

namespace CodeAngel.Domain
{
    /// <summary>
    /// Generates the delete aggregate file for an EntityDef.  If this file already exists, it will
    /// be overwritten.
    /// </summary>
    public static class AggregateDeleteFileGenerator
    {
        #region CreateDeleteAggregateFileAsync

        /// <summary>
        /// Creates and writes to disk the delete aggregate file for the specified EntityDef.
        /// If this file already exists, it will be overwritten.
        /// </summary>
        public static Task CreateDeleteAggregateFileAsync(this EntityDef thisED)
        {
            return Task.Factory.StartNew(() =>
            {
                AggregateDeleteFileGenerator.WriteToDisk(thisED);
            });
        }

        #endregion

        #region WriteToDisk

        /// <summary>
        /// Creates and writes to disk the delete aggregate file for the identified EntityDef. 
        /// If this file already exists, it will be overwritten.
        /// </summary>
        private static void WriteToDisk(EntityDef thisED)
        {
            var ThisFB = new FileBuilder();
            ThisFB.IsAutoGenerated = true;
            ThisFB.ProjectName = thisED.Domain.ProjectName;
            ThisFB.Directory = thisED.EntitiesDirectoryPath;
            ThisFB.FileName = thisED.FileNames.DeleteAggregate();
            ThisFB.Namespace = thisED.Namespace;

            // Add the using namespaces for this file.
            ThisFB.UsingNamespaces.Add("System");
            ThisFB.UsingNamespaces.Add(thisED.Domain.FrameworkNamespace);

            // Add the delete aggregate class.
            ThisFB.CodeUnits.Add(new DeleteAggregateClassBuilder(thisED));

            // Write this file to disk.
            ThisFB.WriteToDisk(OverwriteExistingFile.Yes);
        }

        #endregion

        #region DeleteAggregateClassBuilder

        /// <summary>
        /// Builds the DeleteAggregate class for an EntityDef.
        /// </summary>
        private class DeleteAggregateClassBuilder : ClassBuilder
        {
            #region Constructors

            public DeleteAggregateClassBuilder(EntityDef thisED)
                : base(thisED.ClassNames.DeleteAggregate(), Modifier.PublicPartial)
            {

                base.BaseClass = "DeleteAggregate";

                var UserHasPermissionToDeleteProcedure = this.AddRegion("UserHasPermissionToDelete").AddProcedure("UserHasPermissionToDelete", Modifier.PublicOverride, "bool");
                UserHasPermissionToDeleteProcedure.Body.Add("return this.User.CanDelete{0}();", thisED.Name);

                var GetDtoProcedure = this.AddRegion("GetDto").AddProcedure("GetDto", Modifier.PublicOverride, "IDto");
                GetDtoProcedure.Documentation.Summary="Gets an instance of the DTO, whose ID is set with the identified ID.";
                GetDtoProcedure.Parameters.Add("id", "Guid");
                GetDtoProcedure.Body.Add("var ThisDto = new {0}Dto();", thisED.Name);
                GetDtoProcedure.Body.Add("ThisDto.{0} = id;", thisED.PrimaryKeyPropertyDef.Name);
                GetDtoProcedure.Body.Add("return ThisDto;");
            }

            #endregion
        }

        #endregion
    }
}
